package com.quad.innovators.salesease.common.utils;

import com.quad.innovators.salesease.enums.SystemMouldEnum;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicLong;

/**
 * ID生成工具
 * 20240831 01    000002   00000     17250887   000
 * 日期     模块    经销商  预留位      时间戳差    序列号
 */
public class IdGeneralUtils {

        private static final IdGeneralUtils INSTANCE = new IdGeneralUtils();
        private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
        private final AtomicLong lastTimestamp = new AtomicLong(0);
        private final AtomicLong sequence = new AtomicLong(0);
        private final static long maxSequence = ~(-1L << 3);
        private final static String reservedCode = "000"; //预留位

        private IdGeneralUtils() {
            // 初始化最后时间戳为当前时间戳
            lastTimestamp.set(1725086223000L);
        }

        public synchronized static IdGeneralUtils getInstance() {
            return INSTANCE;
        }

        public synchronized String generateId(SystemMouldEnum systemMouldEnum, String dealerCode) {
            long timestamp = System.currentTimeMillis();
            // 如果当前时间小于上一次ID生成的时间戳，说明时钟回拨，抛出异常
            if (timestamp < lastTimestamp.get()) {
                throw new RuntimeException("Clock moved backwards. Refusing to generate id for the moment.");
            }

            long sequenceVal;
            if (timestamp > lastTimestamp.get()) {
                // 新的毫秒开始，重置序列号
                lastTimestamp.set(timestamp);
                sequence.set(0);
            } else {
                // 同一毫秒内，序列号自增
                sequenceVal = sequence.incrementAndGet();
                if (sequenceVal >= maxSequence) {
                    // 同一毫秒的序列号已经用完，等待下一毫秒
                    while (timestamp <= lastTimestamp.get()) {
                        timestamp = System.currentTimeMillis();
                    }
                    sequence.set(0);
                }
            }
            sequenceVal = sequence.get();
            // 获取当前日期
            String date = LocalDateTime.now().format(DATE_FORMATTER);
            // 获取序列号并格式化
            String sequenceStr = String.format("%03d", sequenceVal);
            // 构造ID
            return date + systemMouldEnum.getCode() + dealerCode + reservedCode + String.valueOf(timestamp).substring(5) + sequenceStr;
        }

        public static void main(String[] args) {
            IdGeneralUtils generator = IdGeneralUtils.getInstance();
            // 测试生成ID
            for (int i = 0; i < 1000; i++) {
                String id = generator.generateId(SystemMouldEnum.USER, "002");
                System.out.println("Generated ID: " + id);
                try {
                    // 模拟高并发环境下的调用间隔
                    Thread.sleep(10); // 等待10毫秒
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }

}
